package net.wanderinghorse.jsonmessage.poster;

import net.wanderinghorse.jsonmessage.*;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.*;
//import sun.net.www.http.*;

/**
 * A RequestPoster implementation which posts a Request via HTTP.
 *
 * Limitations:
 *
 * - See AbstractRequestPoster.
 *
 * - Only supports HTTP[S] POST, not GET.
 *
 * - No proxy support. That has to be set up at the VM level.
 *
 * - Timeout option is not completely honored. The URLConnection API (which is abstract)
 * only supports setting a READ timeout, and not a CONNECT/WRITE timeout,
 * and there are no non-abstract subclasses of it in the standard Java
 * API. The HttpURLConnection type separates read/connect timeouts, but
 * it's abstract. Even if it weren't, we'd have to manually calculate
 * the time it took to connect vs. the read time, and time out accordingly.
 * Bummer.
 *
 * More info about timeouts:
 *
 * http://www.twmacinta.com/myjava/ucon_timeout.php
 *
 * http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4700777
 * in that bug report they claim a fix was released, if they call
 * the current (1.6) API a "fix" then they've got a funny sense of "fixed."
 *
 * http://www.velocityreviews.com/forums/t130657-httpurlconnection-timeout-solution.html
 */
public class HttpRequestPoster extends AbstractRequestPoster {
    private Proxy proxy;
    /**
     * Default-initializes this object.
     */
    public HttpRequestPoster() {
    }

    /**
     * @return The Proxy object used for HTTP proxying, or null
     * if no proxy has been set (or it has subsequently unset).
     */
    public Proxy getHttpProxy() {
        return proxy;
    }

    /**
     * Sets the HTTP proxy used by this object.
     *
     * @param proxy The proxy object. If null then proxying is
     * disabled.
     */
    public void setHttpProxy(final Proxy proxy) {
        synchronized ( this ) {
            this.proxy = proxy;
        }
    }

    /**
     * Sets the HTTP proxy used by this object.
     *
     * @param host The proxy host. If it is null or empty then proxying
     * is disabled.
     * @param port The port number for the proxy.
     */
    public void setHttpProxy( final String host, final int port ) {
        setHttpProxy( ( (null == host) || host.isEmpty() )
                  ? null
                  : new Proxy( Proxy.Type.HTTP, new InetSocketAddress( host, port ) )
                );
    }

    /**
      * Tries to post the given request over HTTP POST using the given options.
      * See the class docs for limitations.
      *
      * Any exceptions will be passed to the opt.getOnError() callback,
      * and are not propagated by this function.
      *
      * @param r The request to post.
      * @param opt The connection options to use for the request.
      */
     @Override
     protected void doPost( Request r, PostOptions opt) throws Exception {
        Response res;
        try {
            res = NetUtil.fetchResponse( r, opt, this.proxy );
            if(null == res) {
                throw new InternalError("This should never happen!");
            }
        }
        catch( Exception ex ) {
            opt.setErrorMessage("Exception ("+ex.getClass().getName()+") while fetching response data: "+ex.toString());
            onPostError( r, opt );
            return;
        }
        onResponse( r, res, opt );
    }
}
